package com.swfgui.managers
{
	import com.swfgui.effects.Tween;
	import com.swfgui.managers.resources.ResourceManager;
	import com.swfgui.utils.ArrayUtil;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundMixer;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	
	/**
	 * 声音管理类
	 * 
	 * @author flashyiyi
	 * 
	 */
	public class SoundManager extends EventDispatcher
	{
		private static var _instacne:SoundManager;
		
		public static  function get instance():SoundManager
		{
			return _instacne ||= new SoundManager();
		}
		
		/**
		 * 默认声音大小，为1.0
		 */		
		public var defaultVolume:Number=1.0;
		
		private var _globalVolume:Number=1.0;
		
		private var _defaultBackgroundMusicVolume:Number=-2.0;
		
		private var _defaultEffectSoundVolume:Number=-2.0;
		
		private var _muteAll:Boolean;
		
		private var _backgroundMusicMute:Boolean;
		
		private var _effectSoundMute:Boolean;		
		    	
    	public function SoundManager():void
    	{
			
    	}
		
		/**
         * 设置全局声音的大小，动态设置全局声音用的
         * @param volume	声音
         * @param pan	声音位置，范围由0到1
         * @param len	变化需要的时间，秒
         */	
	    public function setGlobalVolume(volume:Number,len:Number=0):void
        {
			_globalVolume = volume;
			
        	if (len==0)
			{
				SoundMixer.soundTransform = new SoundTransform(volume);
			}
        	else
			{				
				Tween.to(SoundMixer,len,{volume:volume});
			}
        }
		
		/**
		 * 全局声音的大小，动态设置全局声音用的，默认为1.0，区别于defaultVolume
		 * @return 
		 */
		public function getGlobalVolume():Number
		{
			return _globalVolume;
		}
						
		private var backgroundMusicChanel:SoundChannel;
		private var backgroundMusicSound:Sound;
		private var backgroundStartLen:Number;
		private var backgroundEndLen:Number;
		private var backgroundVolume:Number;
		
		private var prePath:String;
		private var path:String;
         
		/**
		 * 播放背景音乐
		 * @param path 音乐路径
		 * @param volume 音量 0~1，默认-1表示采用defaultBackgroundMusicVolume
		 * @param startLen 渐入时间，秒
		 * @param endLen 淡出时间，秒
		 */
		public function playBackgroundMusic(path:String, volume:Number=0.5, startLen:Number=3, endLen:Number=3):void
		{
			backgroundVolume = volume;
			backgroundStartLen = startLen;
			backgroundEndLen = endLen;			
			this.prePath = this.path;
			this.path = path;
			
			try
			{
				backgroundMusicSound = new Sound(new URLRequest(fixUrl(path)));
				backgroundMusicSound.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
				startBackgroundMusic();	
			}
			catch(e:Error)
			{
				trace("playBackgroundMusic:" + path + ":" + e.message);
			}
		}
		
		private function fixUrl(url:String):String
		{
			if(url.charAt(0) == "/")
			{
				url = url.substr(1);
			}
			
			var revisionList:Dictionary = ResourceManager.revisionList;
			
			if (revisionList && revisionList.hasOwnProperty(url))
			{
				url += (url.lastIndexOf("?") == -1 ? "?" : "&") + "rev=" + revisionList[url];
			}			
			
			return url;
		}
		
		public function playPreBackgroundMusic():void
		{
			if(prePath)
			{
				playBackgroundMusic(prePath, backgroundVolume, backgroundStartLen, backgroundEndLen);
			}
		}
		
		public function stopBackgroundMusic():void
		{
			if(backgroundMusicChanel)
			{
				if(backgroundEndLen > 0)
				{
					Tween.to(backgroundMusicChanel, backgroundEndLen, {volume:0, onComplete:backgroundMusicChanel.stop}) 
				}
				else
				{
					backgroundMusicChanel.stop();
				}
			}
		}
		
		public function startBackgroundMusic():void
		{
			if(muteAll || backgroundMusicMute)
			{
				return;
			}
			
			try
			{
				stopBackgroundMusic();
				
				if(!backgroundMusicSound)
				{
					return;
				}
				var v:Number = (backgroundVolume != -1) ? backgroundVolume : defaultBackgroundMusicVolume;
				backgroundMusicChanel = backgroundMusicSound.play(0, int.MAX_VALUE);
				if(backgroundStartLen > 0)
				{					
					backgroundMusicChanel.soundTransform = new SoundTransform(0);
					Tween.to(backgroundMusicChanel, backgroundStartLen, {volume:v});
				}
				else
				{
					backgroundMusicChanel.soundTransform = new SoundTransform(v);
				}
			}
			catch(e:Error)
			{
				trace("playBackgroundMusic:" + backgroundMusicSound.url + ":" + e.message);
			}	
		}
		
		private var effectSounds:Array = [];
         
		/**
		 * 播放音效
		 * @param path 音乐路径
		 * @param volume  音量 0~1，默认-1表示采用defaultEffectSoundVolume
		 * @param loop
		 */
		public function playEffectSound(path:String, volume:Number=-1, loop:int=1):void
		{
			if(muteAll || effectSoundMute)
			{
				return;
			}
			
			try
			{				
				var s:Sound = new Sound(new URLRequest(fixUrl(path)));
				s.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
				var c:SoundChannel = s.play(0, loop);				
				c.soundTransform = new SoundTransform((volume != -1) ? volume : defaultEffectSoundVolume);
				c.addEventListener(Event.SOUND_COMPLETE, onEffectCpt);
				effectSounds.push(c);
				
			}
			catch(e:Error)
			{
				trace("playEffectMusic:" + path + ":" + e.message);
			}	
		}
		
		protected function onError(event:Event):void
		{
			trace(event.toString());
		}
		
		protected function onEffectCpt(event:Event):void
		{
			var c:SoundChannel = event.currentTarget as SoundChannel;
			c.removeEventListener(Event.SOUND_COMPLETE, onEffectCpt);
			ArrayUtil.deleteItem(c, effectSounds);
		}
		
		public function stopEffectSound():void
		{
			for each(var c:SoundChannel in effectSounds)
			{
				c.stop();
			}
			effectSounds.length = 0;
		}

		public function get backgroundMusicMute():Boolean
		{
			return _backgroundMusicMute;
		}

		public function set backgroundMusicMute(value:Boolean):void
		{
			_backgroundMusicMute = value;
			if(value)
			{
				stopBackgroundMusic();
			}
		}

		public function get effectSoundMute():Boolean
		{
			return _effectSoundMute;
		}

		public function set effectSoundMute(value:Boolean):void
		{
			_effectSoundMute = value;
			if(value)
			{
				stopEffectSound();
			}
		}

		public function get muteAll():Boolean
		{
			return _muteAll;
		}

		public function set muteAll(value:Boolean):void
		{
			_muteAll = value;
			if(value)
			{
				SoundMixer.stopAll();
			}
			else
			{
				startBackgroundMusic();
			}
		}

		/**
		 * 默认背景音乐音量，不设置，则和defaultVolume相同
		 * @return 
		 */
		public function get defaultBackgroundMusicVolume():Number
		{
			return _defaultBackgroundMusicVolume != -2 ? _defaultBackgroundMusicVolume : defaultVolume;
		}

		public function set defaultBackgroundMusicVolume(value:Number):void
		{
			_defaultBackgroundMusicVolume = value;
		}

		/**
		 * 默认音效音量，不设置，则和defaultVolume相同
		 * @return 
		 */
		public function get defaultEffectSoundVolume():Number
		{
			return _defaultEffectSoundVolume != -2 ? _defaultEffectSoundVolume : defaultVolume;
		}

		public function set defaultEffectSoundVolume(value:Number):void
		{
			_defaultEffectSoundVolume = value;
		}
	}
}